#include <stdint.h>

// SBI v0.2+ ECALL: a7=EID, a6=FID, a0..a5=args
static inline long sbi_ecall(long eid, long fid, long a0v, long a1v, long a2v, long a3v, long a4v, long a5v) {
    register long a0 asm("a0") = a0v;
    register long a1 asm("a1") = a1v;
    register long a2 asm("a2") = a2v;
    register long a3 asm("a3") = a3v;
    register long a4 asm("a4") = a4v;
    register long a5 asm("a5") = a5v;
    register long a6 asm("a6") = fid;
    register long a7 asm("a7") = eid;
    asm volatile ("ecall" : "+r"(a0) : "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6), "r"(a7) : "memory");
    return a0; // return value per SBI spec
}

// SBI EIDs and FIDs
#define SBI_EID_CONSOLE_PUTCHAR  0x1
#define SBI_FID_CONSOLE_PUTCHAR  0x0

#define SBI_EID_SRST             0x8
#define SBI_FID_SRST_RESET       0x0
#define SBI_SRST_RESET_TYPE_SHUTDOWN 0x0
#define SBI_SRST_RESET_REASON_NONE   0x0

static void sbi_putc(char c) {
    sbi_ecall(SBI_EID_CONSOLE_PUTCHAR, SBI_FID_CONSOLE_PUTCHAR, (long)(unsigned char)c, 0, 0, 0, 0, 0);
}

static void sbi_puts(const char *s) {
    while (*s) {
        if (*s == '\n') sbi_putc('\r');
        sbi_putc(*s++);
    }
}

static void sbi_shutdown(void) {
    (void)sbi_ecall(SBI_EID_SRST, SBI_FID_SRST_RESET, SBI_SRST_RESET_TYPE_SHUTDOWN, SBI_SRST_RESET_REASON_NONE, 0, 0, 0, 0);
}

void kmain(void) {
    sbi_puts("Hello via SBI v0.2 from rv64 kernel!\n");
    sbi_shutdown();
    for (;;) { }
}
